From bd24ca5b18917f86c9cc3559ab4d0cac5bb5561a Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Wed, 18 Jan 2017 04:07:09 +0100 Subject: [PATCH] vulkan: Add support for unblurred box-shadow --- gsk/Makefile.am | 10 +- gsk/gskvulkanboxshadowpipeline.c | 161 ++++++++++++++++++++++++ gsk/gskvulkanboxshadowpipelineprivate.h | 38 ++++++ gsk/gskvulkanrender.c | 9 +- gsk/gskvulkanrenderpass.c | 99 ++++++++++++++- gsk/gskvulkanrenderprivate.h | 6 + gsk/resources/vulkan/inset-shadow.frag | 26 ++++ gsk/resources/vulkan/inset-shadow.vert | 45 +++++++ gsk/resources/vulkan/outset-shadow.frag | 26 ++++ gsk/resources/vulkan/outset-shadow.vert | 45 +++++++ 10 files changed, 460 insertions(+), 5 deletions(-) create mode 100644 gsk/gskvulkanboxshadowpipeline.c create mode 100644 gsk/gskvulkanboxshadowpipelineprivate.h create mode 100644 gsk/resources/vulkan/inset-shadow.frag create mode 100644 gsk/resources/vulkan/inset-shadow.vert create mode 100644 gsk/resources/vulkan/outset-shadow.frag create mode 100644 gsk/resources/vulkan/outset-shadow.vert diff --git a/gsk/Makefile.am b/gsk/Makefile.am index 9d13253956..bc7829e51e 100644 --- a/gsk/Makefile.am +++ b/gsk/Makefile.am @@ -26,6 +26,7 @@ if HAVE_VULKAN gsk_private_vulkan_source_h = \ gskvulkanblendpipelineprivate.h \ gskvulkanborderpipelineprivate.h \ + gskvulkanboxshadowpipelineprivate.h \ gskvulkanbufferprivate.h \ gskvulkanclipprivate.h \ gskvulkancolorpipelineprivate.h \ @@ -43,6 +44,7 @@ gsk_private_vulkan_source_h = \ gsk_private_vulkan_source_c = \ gskvulkanblendpipeline.c \ gskvulkanborderpipeline.c \ + gskvulkanboxshadowpipeline.c \ gskvulkanbuffer.c \ gskvulkanclip.c \ gskvulkancolorpipeline.c \ @@ -67,13 +69,17 @@ gsk_private_vulkan_fragment_shaders = \ resources/vulkan/border.frag \ resources/vulkan/color.frag \ resources/vulkan/color-matrix.frag \ - resources/vulkan/linear.frag + resources/vulkan/inset-shadow.frag \ + resources/vulkan/linear.frag \ + resources/vulkan/outset-shadow.frag gsk_private_vulkan_vertex_shaders = \ resources/vulkan/blend.vert \ resources/vulkan/border.vert \ resources/vulkan/color.vert \ resources/vulkan/color-matrix.vert \ - resources/vulkan/linear.vert + resources/vulkan/inset-shadow.vert \ + resources/vulkan/linear.vert \ + resources/vulkan/outset-shadow.vert gsk_private_vulkan_shaders = \ $(gsk_private_vulkan_fragment_shaders) \ $(gsk_private_vulkan_vertex_shaders) diff --git a/gsk/gskvulkanboxshadowpipeline.c b/gsk/gskvulkanboxshadowpipeline.c new file mode 100644 index 0000000000..f5261261ab --- /dev/null +++ b/gsk/gskvulkanboxshadowpipeline.c @@ -0,0 +1,161 @@ +#include "config.h" + +#include "gskvulkanboxshadowpipelineprivate.h" + +#include "gskroundedrectprivate.h" + +struct _GskVulkanBoxShadowPipeline +{ + GObject parent_instance; +}; + +typedef struct _GskVulkanBoxShadowInstance GskVulkanBoxShadowInstance; + +struct _GskVulkanBoxShadowInstance +{ + float outline[12]; + float color[4]; + float offset[2]; + float spread; + float blur_radius; +}; + +G_DEFINE_TYPE (GskVulkanBoxShadowPipeline, gsk_vulkan_box_shadow_pipeline, GSK_TYPE_VULKAN_PIPELINE) + +static const VkPipelineVertexInputStateCreateInfo * +gsk_vulkan_box_shadow_pipeline_get_input_state_create_info (GskVulkanPipeline *self) +{ + static const VkVertexInputBindingDescription vertexBindingDescriptions[] = { + { + .binding = 0, + .stride = sizeof (GskVulkanBoxShadowInstance), + .inputRate = VK_VERTEX_INPUT_RATE_INSTANCE + } + }; + static const VkVertexInputAttributeDescription vertexInputAttributeDescription[] = { + { + .location = 0, + .binding = 0, + .format = VK_FORMAT_R32G32B32A32_SFLOAT, + .offset = G_STRUCT_OFFSET (GskVulkanBoxShadowInstance, outline), + }, + { + .location = 1, + .binding = 0, + .format = VK_FORMAT_R32G32B32A32_SFLOAT, + .offset = G_STRUCT_OFFSET (GskVulkanBoxShadowInstance, outline) + 4 * sizeof (float), + }, + { + .location = 2, + .binding = 0, + .format = VK_FORMAT_R32G32B32A32_SFLOAT, + .offset = G_STRUCT_OFFSET (GskVulkanBoxShadowInstance, outline) + 8 * sizeof (float), + }, + { + .location = 3, + .binding = 0, + .format = VK_FORMAT_R32G32B32A32_SFLOAT, + .offset = G_STRUCT_OFFSET (GskVulkanBoxShadowInstance, color), + }, + { + .location = 4, + .binding = 0, + .format = VK_FORMAT_R32G32_SFLOAT, + .offset = G_STRUCT_OFFSET (GskVulkanBoxShadowInstance, offset), + }, + { + .location = 5, + .binding = 0, + .format = VK_FORMAT_R32_SFLOAT, + .offset = G_STRUCT_OFFSET (GskVulkanBoxShadowInstance, spread), + }, + { + .location = 6, + .binding = 0, + .format = VK_FORMAT_R32_SFLOAT, + .offset = G_STRUCT_OFFSET (GskVulkanBoxShadowInstance, blur_radius), + } + }; + static const VkPipelineVertexInputStateCreateInfo info = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, + .vertexBindingDescriptionCount = G_N_ELEMENTS (vertexBindingDescriptions), + .pVertexBindingDescriptions = vertexBindingDescriptions, + .vertexAttributeDescriptionCount = G_N_ELEMENTS (vertexInputAttributeDescription), + .pVertexAttributeDescriptions = vertexInputAttributeDescription + }; + + return &info; +} + +static void +gsk_vulkan_box_shadow_pipeline_finalize (GObject *gobject) +{ + //GskVulkanBoxShadowPipeline *self = GSK_VULKAN_BOX_SHADOW_PIPELINE (gobject); + + G_OBJECT_CLASS (gsk_vulkan_box_shadow_pipeline_parent_class)->finalize (gobject); +} + +static void +gsk_vulkan_box_shadow_pipeline_class_init (GskVulkanBoxShadowPipelineClass *klass) +{ + GskVulkanPipelineClass *pipeline_class = GSK_VULKAN_PIPELINE_CLASS (klass); + + G_OBJECT_CLASS (klass)->finalize = gsk_vulkan_box_shadow_pipeline_finalize; + + pipeline_class->get_input_state_create_info = gsk_vulkan_box_shadow_pipeline_get_input_state_create_info; +} + +static void +gsk_vulkan_box_shadow_pipeline_init (GskVulkanBoxShadowPipeline *self) +{ +} + +GskVulkanPipeline * +gsk_vulkan_box_shadow_pipeline_new (GskVulkanPipelineLayout *layout, + const char *shader_name, + VkRenderPass render_pass) +{ + return gsk_vulkan_pipeline_new (GSK_TYPE_VULKAN_BOX_SHADOW_PIPELINE, layout, shader_name, render_pass); +} + +gsize +gsk_vulkan_box_shadow_pipeline_count_vertex_data (GskVulkanBoxShadowPipeline *pipeline) +{ + return sizeof (GskVulkanBoxShadowInstance); +} + +void +gsk_vulkan_box_shadow_pipeline_collect_vertex_data (GskVulkanBoxShadowPipeline *pipeline, + guchar *data, + const GskRoundedRect *outline, + const GdkRGBA *color, + float dx, + float dy, + float spread, + float blur_radius) +{ + GskVulkanBoxShadowInstance *instance = (GskVulkanBoxShadowInstance *) data; + + gsk_rounded_rect_to_float (outline, instance->outline); + instance->color[0] = color->red; + instance->color[1] = color->green; + instance->color[2] = color->blue; + instance->color[3] = color->alpha; + instance->offset[0] = dx; + instance->offset[1] = dy; + instance->spread = spread; + instance->blur_radius = blur_radius; +} + +gsize +gsk_vulkan_box_shadow_pipeline_draw (GskVulkanBoxShadowPipeline *pipeline, + VkCommandBuffer command_buffer, + gsize offset, + gsize n_commands) +{ + vkCmdDraw (command_buffer, + 6 * 8, n_commands, + 0, offset); + + return n_commands; +} diff --git a/gsk/gskvulkanboxshadowpipelineprivate.h b/gsk/gskvulkanboxshadowpipelineprivate.h new file mode 100644 index 0000000000..930480de15 --- /dev/null +++ b/gsk/gskvulkanboxshadowpipelineprivate.h @@ -0,0 +1,38 @@ +#ifndef __GSK_VULKAN_BOX_SHADOW_PIPELINE_PRIVATE_H__ +#define __GSK_VULKAN_BOX_SHADOW_PIPELINE_PRIVATE_H__ + +#include + +#include "gskvulkanpipelineprivate.h" +#include "gskroundedrect.h" + +G_BEGIN_DECLS + +typedef struct _GskVulkanBoxShadowPipelineLayout GskVulkanBoxShadowPipelineLayout; + +#define GSK_TYPE_VULKAN_BOX_SHADOW_PIPELINE (gsk_vulkan_box_shadow_pipeline_get_type ()) + +G_DECLARE_FINAL_TYPE (GskVulkanBoxShadowPipeline, gsk_vulkan_box_shadow_pipeline, GSK, VULKAN_BOX_SHADOW_PIPELINE, GskVulkanPipeline) + +GskVulkanPipeline * gsk_vulkan_box_shadow_pipeline_new (GskVulkanPipelineLayout * layout, + const char *shader_name, + VkRenderPass render_pass); + +gsize gsk_vulkan_box_shadow_pipeline_count_vertex_data (GskVulkanBoxShadowPipeline *pipeline); +void gsk_vulkan_box_shadow_pipeline_collect_vertex_data (GskVulkanBoxShadowPipeline *pipeline, + guchar *data, + const GskRoundedRect *outline, + const GdkRGBA *color, + float dx, + float dy, + float spread, + float blur_radius); + +gsize gsk_vulkan_box_shadow_pipeline_draw (GskVulkanBoxShadowPipeline *pipeline, + VkCommandBuffer command_buffer, + gsize offset, + gsize n_commands); + +G_END_DECLS + +#endif /* __GSK_VULKAN_BOX_SHADOW_PIPELINE_PRIVATE_H__ */ diff --git a/gsk/gskvulkanrender.c b/gsk/gskvulkanrender.c index cd362d00b1..515a39c308 100644 --- a/gsk/gskvulkanrender.c +++ b/gsk/gskvulkanrender.c @@ -10,6 +10,7 @@ #include "gskvulkanblendpipelineprivate.h" #include "gskvulkanborderpipelineprivate.h" +#include "gskvulkanboxshadowpipelineprivate.h" #include "gskvulkancolorpipelineprivate.h" #include "gskvulkaneffectpipelineprivate.h" #include "gskvulkanlineargradientpipelineprivate.h" @@ -330,7 +331,13 @@ gsk_vulkan_render_get_pipeline (GskVulkanRender *self, { "color-matrix-clip-rounded", gsk_vulkan_effect_pipeline_new }, { "border", gsk_vulkan_border_pipeline_new }, { "border-clip", gsk_vulkan_border_pipeline_new }, - { "border-clip-rounded", gsk_vulkan_border_pipeline_new } + { "border-clip-rounded", gsk_vulkan_border_pipeline_new }, + { "inset-shadow", gsk_vulkan_box_shadow_pipeline_new }, + { "inset-shadow-clip", gsk_vulkan_box_shadow_pipeline_new }, + { "inset-shadow-clip-rounded", gsk_vulkan_box_shadow_pipeline_new }, + { "outset-shadow", gsk_vulkan_box_shadow_pipeline_new }, + { "outset-shadow-clip", gsk_vulkan_box_shadow_pipeline_new }, + { "outset-shadow-clip-rounded", gsk_vulkan_box_shadow_pipeline_new }, }; g_return_val_if_fail (type < GSK_VULKAN_N_PIPELINES, NULL); diff --git a/gsk/gskvulkanrenderpass.c b/gsk/gskvulkanrenderpass.c index 4d2d50270f..61bb6c7e20 100644 --- a/gsk/gskvulkanrenderpass.c +++ b/gsk/gskvulkanrenderpass.c @@ -8,6 +8,7 @@ #include "gskroundedrectprivate.h" #include "gskvulkanblendpipelineprivate.h" #include "gskvulkanborderpipelineprivate.h" +#include "gskvulkanboxshadowpipelineprivate.h" #include "gskvulkanclipprivate.h" #include "gskvulkancolorpipelineprivate.h" #include "gskvulkaneffectpipelineprivate.h" @@ -32,6 +33,8 @@ typedef enum { GSK_VULKAN_OP_OPACITY, GSK_VULKAN_OP_COLOR_MATRIX, GSK_VULKAN_OP_BORDER, + GSK_VULKAN_OP_INSET_SHADOW, + GSK_VULKAN_OP_OUTSET_SHADOW, /* GskVulkanOpPushConstants */ GSK_VULKAN_OP_PUSH_VERTEX_CONSTANTS } GskVulkanOpType; @@ -112,8 +115,6 @@ gsk_vulkan_render_pass_add_node (GskVulkanRenderPass *self, case GSK_NOT_A_RENDER_NODE: g_assert_not_reached (); return; - case GSK_INSET_SHADOW_NODE: - case GSK_OUTSET_SHADOW_NODE: case GSK_REPEAT_NODE: case GSK_SHADOW_NODE: case GSK_BLEND_NODE: @@ -121,6 +122,38 @@ gsk_vulkan_render_pass_add_node (GskVulkanRenderPass *self, default: FALLBACK ("Unsupported node '%s'\n", node->node_class->type_name); + case GSK_INSET_SHADOW_NODE: + if (gsk_inset_shadow_node_get_blur_radius (node) > 0) + FALLBACK ("Blur support not implemented for inset shadows\n"); + else if (gsk_vulkan_clip_contains_rect (&constants->clip, &node->bounds)) + pipeline_type = GSK_VULKAN_PIPELINE_INSET_SHADOW; + else if (constants->clip.type == GSK_VULKAN_CLIP_RECT) + pipeline_type = GSK_VULKAN_PIPELINE_INSET_SHADOW_CLIP; + else if (constants->clip.type == GSK_VULKAN_CLIP_ROUNDED_CIRCULAR) + pipeline_type = GSK_VULKAN_PIPELINE_INSET_SHADOW_CLIP_ROUNDED; + else + FALLBACK ("Inset shadow nodes can't deal with clip type %u\n", constants->clip.type); + op.type = GSK_VULKAN_OP_INSET_SHADOW; + op.render.pipeline = gsk_vulkan_render_get_pipeline (render, pipeline_type); + g_array_append_val (self->render_ops, op); + return; + + case GSK_OUTSET_SHADOW_NODE: + if (gsk_outset_shadow_node_get_blur_radius (node) > 0) + FALLBACK ("Blur support not implemented for outset shadows\n"); + else if (gsk_vulkan_clip_contains_rect (&constants->clip, &node->bounds)) + pipeline_type = GSK_VULKAN_PIPELINE_OUTSET_SHADOW; + else if (constants->clip.type == GSK_VULKAN_CLIP_RECT) + pipeline_type = GSK_VULKAN_PIPELINE_OUTSET_SHADOW_CLIP; + else if (constants->clip.type == GSK_VULKAN_CLIP_ROUNDED_CIRCULAR) + pipeline_type = GSK_VULKAN_PIPELINE_OUTSET_SHADOW_CLIP_ROUNDED; + else + FALLBACK ("Outset shadow nodes can't deal with clip type %u\n", constants->clip.type); + op.type = GSK_VULKAN_OP_OUTSET_SHADOW; + op.render.pipeline = gsk_vulkan_render_get_pipeline (render, pipeline_type); + g_array_append_val (self->render_ops, op); + return; + case GSK_CAIRO_NODE: if (gsk_cairo_node_get_surface (node) == NULL) return; @@ -520,6 +553,8 @@ gsk_vulkan_render_pass_upload (GskVulkanRenderPass *self, case GSK_VULKAN_OP_LINEAR_GRADIENT: case GSK_VULKAN_OP_PUSH_VERTEX_CONSTANTS: case GSK_VULKAN_OP_BORDER: + case GSK_VULKAN_OP_INSET_SHADOW: + case GSK_VULKAN_OP_OUTSET_SHADOW: break; } } @@ -569,6 +604,12 @@ gsk_vulkan_render_pass_count_vertex_data (GskVulkanRenderPass *self) n_bytes += op->render.vertex_count; break; + case GSK_VULKAN_OP_INSET_SHADOW: + case GSK_VULKAN_OP_OUTSET_SHADOW: + op->render.vertex_count = gsk_vulkan_box_shadow_pipeline_count_vertex_data (GSK_VULKAN_BOX_SHADOW_PIPELINE (op->render.pipeline)); + n_bytes += op->render.vertex_count; + break; + default: g_assert_not_reached (); case GSK_VULKAN_OP_PUSH_VERTEX_CONSTANTS: @@ -682,6 +723,36 @@ gsk_vulkan_render_pass_collect_vertex_data (GskVulkanRenderPass *self, } break; + case GSK_VULKAN_OP_INSET_SHADOW: + { + op->render.vertex_offset = offset + n_bytes; + gsk_vulkan_box_shadow_pipeline_collect_vertex_data (GSK_VULKAN_BOX_SHADOW_PIPELINE (op->render.pipeline), + data + n_bytes + offset, + gsk_inset_shadow_node_peek_outline (op->render.node), + gsk_inset_shadow_node_peek_color (op->render.node), + gsk_inset_shadow_node_get_dx (op->render.node), + gsk_inset_shadow_node_get_dy (op->render.node), + gsk_inset_shadow_node_get_spread (op->render.node), + gsk_inset_shadow_node_get_blur_radius (op->render.node)); + n_bytes += op->render.vertex_count; + } + break; + + case GSK_VULKAN_OP_OUTSET_SHADOW: + { + op->render.vertex_offset = offset + n_bytes; + gsk_vulkan_box_shadow_pipeline_collect_vertex_data (GSK_VULKAN_BOX_SHADOW_PIPELINE (op->render.pipeline), + data + n_bytes + offset, + gsk_outset_shadow_node_peek_outline (op->render.node), + gsk_outset_shadow_node_peek_color (op->render.node), + gsk_outset_shadow_node_get_dx (op->render.node), + gsk_outset_shadow_node_get_dy (op->render.node), + gsk_outset_shadow_node_get_spread (op->render.node), + gsk_outset_shadow_node_get_blur_radius (op->render.node)); + n_bytes += op->render.vertex_count; + } + break; + default: g_assert_not_reached (); case GSK_VULKAN_OP_PUSH_VERTEX_CONSTANTS: @@ -723,6 +794,8 @@ gsk_vulkan_render_pass_reserve_descriptor_sets (GskVulkanRenderPass *self, case GSK_VULKAN_OP_LINEAR_GRADIENT: case GSK_VULKAN_OP_PUSH_VERTEX_CONSTANTS: case GSK_VULKAN_OP_BORDER: + case GSK_VULKAN_OP_INSET_SHADOW: + case GSK_VULKAN_OP_OUTSET_SHADOW: break; } } @@ -889,6 +962,28 @@ gsk_vulkan_render_pass_draw (GskVulkanRenderPass *self, current_draw_index, 1); break; + case GSK_VULKAN_OP_INSET_SHADOW: + case GSK_VULKAN_OP_OUTSET_SHADOW: + if (current_pipeline != op->render.pipeline) + { + current_pipeline = op->render.pipeline; + vkCmdBindPipeline (command_buffer, + VK_PIPELINE_BIND_POINT_GRAPHICS, + gsk_vulkan_pipeline_get_pipeline (current_pipeline)); + vkCmdBindVertexBuffers (command_buffer, + 0, + 1, + (VkBuffer[1]) { + gsk_vulkan_buffer_get_buffer (vertex_buffer) + }, + (VkDeviceSize[1]) { op->render.vertex_offset }); + current_draw_index = 0; + } + current_draw_index += gsk_vulkan_box_shadow_pipeline_draw (GSK_VULKAN_BOX_SHADOW_PIPELINE (current_pipeline), + command_buffer, + current_draw_index, 1); + break; + case GSK_VULKAN_OP_PUSH_VERTEX_CONSTANTS: gsk_vulkan_push_constants_push (&op->constants.constants, command_buffer, diff --git a/gsk/gskvulkanrenderprivate.h b/gsk/gskvulkanrenderprivate.h index ea9c751637..29860f086e 100644 --- a/gsk/gskvulkanrenderprivate.h +++ b/gsk/gskvulkanrenderprivate.h @@ -25,6 +25,12 @@ typedef enum { GSK_VULKAN_PIPELINE_BORDER, GSK_VULKAN_PIPELINE_BORDER_CLIP, GSK_VULKAN_PIPELINE_BORDER_CLIP_ROUNDED, + GSK_VULKAN_PIPELINE_INSET_SHADOW, + GSK_VULKAN_PIPELINE_INSET_SHADOW_CLIP, + GSK_VULKAN_PIPELINE_INSET_SHADOW_CLIP_ROUNDED, + GSK_VULKAN_PIPELINE_OUTSET_SHADOW, + GSK_VULKAN_PIPELINE_OUTSET_SHADOW_CLIP, + GSK_VULKAN_PIPELINE_OUTSET_SHADOW_CLIP_ROUNDED, /* add more */ GSK_VULKAN_N_PIPELINES } GskVulkanPipelineType; diff --git a/gsk/resources/vulkan/inset-shadow.frag b/gsk/resources/vulkan/inset-shadow.frag new file mode 100644 index 0000000000..594b325c47 --- /dev/null +++ b/gsk/resources/vulkan/inset-shadow.frag @@ -0,0 +1,26 @@ +#version 420 core + +#include "clip.frag.glsl" +#include "rounded-rect.glsl" + +layout(location = 0) in vec2 inPos; +layout(location = 1) in flat vec4 inOutline; +layout(location = 2) in flat vec4 inOutlineCornerWidths; +layout(location = 3) in flat vec4 inOutlineCornerHeights; +layout(location = 4) in flat vec4 inColor; +layout(location = 5) in flat vec2 inOffset; +layout(location = 6) in flat float inSpread; + +layout(location = 0) out vec4 color; + +void main() +{ + RoundedRect outline = RoundedRect (vec4(inOutline.xy, inOutline.xy + inOutline.zw), inOutlineCornerWidths, inOutlineCornerHeights); + RoundedRect inside = rounded_rect_shrink (outline, vec4(inSpread)); + + color = vec4(inColor.rgb * inColor.a, inColor.a); + color = color * clamp (rounded_rect_coverage (outline, inPos) - + rounded_rect_coverage (inside, inPos - inOffset), + 0.0, 1.0); + color = clip (inPos, color); +} diff --git a/gsk/resources/vulkan/inset-shadow.vert b/gsk/resources/vulkan/inset-shadow.vert new file mode 100644 index 0000000000..7b76e532d5 --- /dev/null +++ b/gsk/resources/vulkan/inset-shadow.vert @@ -0,0 +1,45 @@ +#version 420 core + +#include "clip.vert.glsl" + +layout(location = 0) in vec4 inOutline; +layout(location = 1) in vec4 inOutlineCornerWidths; +layout(location = 2) in vec4 inOutlineCornerHeights; +layout(location = 3) in vec4 inColor; +layout(location = 4) in vec2 inOffset; +layout(location = 5) in float inSpread; +layout(location = 6) in float inBlurRadius; + +layout(location = 0) out vec2 outPos; +layout(location = 1) out flat vec4 outOutline; +layout(location = 2) out flat vec4 outOutlineCornerWidths; +layout(location = 3) out flat vec4 outOutlineCornerHeights; +layout(location = 4) out flat vec4 outColor; +layout(location = 5) out flat vec2 outOffset; +layout(location = 6) out flat float outSpread; + +out gl_PerVertex { + vec4 gl_Position; +}; + +vec2 offsets[6] = { vec2(0.0, 0.0), + vec2(1.0, 0.0), + vec2(0.0, 1.0), + vec2(0.0, 1.0), + vec2(1.0, 0.0), + vec2(1.0, 1.0) }; + +void main() { + vec4 rect = clip (inOutline); + + vec2 pos = rect.xy + rect.zw * offsets[gl_VertexIndex]; + gl_Position = push.mvp * vec4 (pos, 0.0, 1.0); + outPos = pos; + + outOutline = inOutline; + outOutlineCornerWidths = inOutlineCornerWidths; + outOutlineCornerHeights = inOutlineCornerHeights; + outColor = inColor; + outOffset = inOffset; + outSpread = inSpread; +} diff --git a/gsk/resources/vulkan/outset-shadow.frag b/gsk/resources/vulkan/outset-shadow.frag new file mode 100644 index 0000000000..0d496a68e7 --- /dev/null +++ b/gsk/resources/vulkan/outset-shadow.frag @@ -0,0 +1,26 @@ +#version 420 core + +#include "clip.frag.glsl" +#include "rounded-rect.glsl" + +layout(location = 0) in vec2 inPos; +layout(location = 1) in flat vec4 inOutline; +layout(location = 2) in flat vec4 inOutlineCornerWidths; +layout(location = 3) in flat vec4 inOutlineCornerHeights; +layout(location = 4) in flat vec4 inColor; +layout(location = 5) in flat vec2 inOffset; +layout(location = 6) in flat float inSpread; + +layout(location = 0) out vec4 color; + +void main() +{ + RoundedRect outline = RoundedRect (vec4(inOutline.xy, inOutline.xy + inOutline.zw), inOutlineCornerWidths, inOutlineCornerHeights); + RoundedRect outside = rounded_rect_shrink (outline, vec4(-inSpread)); + + color = vec4(inColor.rgb * inColor.a, inColor.a); + color = color * clamp (rounded_rect_coverage (outside, inPos - inOffset) - + rounded_rect_coverage (outline, inPos - inOffset), + 0.0, 1.0); + color = clip (inPos, color); +} diff --git a/gsk/resources/vulkan/outset-shadow.vert b/gsk/resources/vulkan/outset-shadow.vert new file mode 100644 index 0000000000..7b76e532d5 --- /dev/null +++ b/gsk/resources/vulkan/outset-shadow.vert @@ -0,0 +1,45 @@ +#version 420 core + +#include "clip.vert.glsl" + +layout(location = 0) in vec4 inOutline; +layout(location = 1) in vec4 inOutlineCornerWidths; +layout(location = 2) in vec4 inOutlineCornerHeights; +layout(location = 3) in vec4 inColor; +layout(location = 4) in vec2 inOffset; +layout(location = 5) in float inSpread; +layout(location = 6) in float inBlurRadius; + +layout(location = 0) out vec2 outPos; +layout(location = 1) out flat vec4 outOutline; +layout(location = 2) out flat vec4 outOutlineCornerWidths; +layout(location = 3) out flat vec4 outOutlineCornerHeights; +layout(location = 4) out flat vec4 outColor; +layout(location = 5) out flat vec2 outOffset; +layout(location = 6) out flat float outSpread; + +out gl_PerVertex { + vec4 gl_Position; +}; + +vec2 offsets[6] = { vec2(0.0, 0.0), + vec2(1.0, 0.0), + vec2(0.0, 1.0), + vec2(0.0, 1.0), + vec2(1.0, 0.0), + vec2(1.0, 1.0) }; + +void main() { + vec4 rect = clip (inOutline); + + vec2 pos = rect.xy + rect.zw * offsets[gl_VertexIndex]; + gl_Position = push.mvp * vec4 (pos, 0.0, 1.0); + outPos = pos; + + outOutline = inOutline; + outOutlineCornerWidths = inOutlineCornerWidths; + outOutlineCornerHeights = inOutlineCornerHeights; + outColor = inColor; + outOffset = inOffset; + outSpread = inSpread; +} -- 2.30.2